﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Security;
using Newtonsoft.Json;
using System.Reflection;
using System.Linq;

namespace KM_ClientPrintActiveX
{
    //UserControl
    [Guid("AAABBBCC-D8CB-44B9-BD8C-F7D8348F6DFE"), ProgId("KM_ClientPrintActiveX.KMPrintControl")]
    [SecuritySafeCritical]
    public partial class KMPrintControl: UserControl, IObjectSafety
    {
        BarTender.Application btApp = new BarTender.ApplicationClass();
        public KMPrintControl()
        {
            InitializeComponent();
        }

        #region IObjectSafety 成员 格式固定  

        private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
        private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
        private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
        private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
        private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";

        private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
        private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
        private const int S_OK = 0;
        private const int E_FAIL = unchecked((int)0x80004005);
        private const int E_NOINTERFACE = unchecked((int)0x80004002);

        private bool _fSafeForScripting = true;
        private bool _fSafeForInitializing = true;

        public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
        {
            int Rslt = E_FAIL;

            string strGUID = riid.ToString("B");
            pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForScripting == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForInitializing == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }

        public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
        {
            int Rslt = E_FAIL;
            string strGUID = riid.ToString("B");
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
                        Rslt = S_OK;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
                        Rslt = S_OK;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }

        #endregion

        public void BTQuit()
        {
            btApp.Quit();
        }

        public void PrintPreview(string JsonData, string FileName)
        {
            if (string.IsNullOrWhiteSpace(JsonData))
            {
                MessageBox.Show("打印参数不能为空");
                return;
            }
            if (string.IsNullOrWhiteSpace(FileName))
            {
                MessageBox.Show("文件名不能为空");
                return;
            }
            
            //初始化引擎
            Process process = new Process();
            try
            {
                PrintDataSourceList model = GetModel<PrintDataSourceList>(JsonData);
                var printDataTable = LinqToDataTable(model.list.ToList());

                BarTender.Format btFormat = btApp.Formats.Open(@""+ FileName + "", false, "");
                string columnData = btFormat.NamedSubStrings.GetAll("[", "]");
                columnData = columnData.Substring(0, columnData.Length - 1);
                string[] sArray = columnData.Split(']');
                for (int i = 0; i < sArray.Length; i++)
                {
                    string textName = string.Empty;
                    string valveData = string.Empty;
                    try
                    {
                        string[] dataName = sArray[i].Split('[');
                        textName = dataName[0];
                        valveData = printDataTable.Rows[0][textName].ToString();
                        btFormat.SetNamedSubStringValue(textName, valveData);
                    }
                    catch
                    {
                        btFormat.SetNamedSubStringValue(textName, "");
                        //btFormat.SetNamedSubStringValue("SHOETREENO", "9897"); //型号
                    }

                }

                btFormat.Save();
                btFormat.Close();
                btApp.Quit();

                //默认加载的模板文件
                ProcessStartInfo processStartInfo = new ProcessStartInfo(@""+ FileName + "");
                process.StartInfo = processStartInfo;
                //打开默认保存的模板文件
                process.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            finally
            {
                if (process != null)
                {
                    process.Dispose();
                    process.Close();
                }
            }
        }

        /// <summary>
        /// 转换成实体类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="JsonData"></param>
        /// <returns></returns>
        public T GetModel<T>(string JsonData)
        {
            var model = default(T);
            try
            {
                model = JsonConvert.DeserializeObject<T>(JsonData);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return model;
        }

        /// <summary>
        /// 将IEnumerable<T>类型的集合转换为DataTable类型 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="varlist"></param>
        /// <returns></returns>
        public static DataTable LinqToDataTable<T>(IEnumerable<T> varlist)
        {   //定义要返回的DataTable对象
            var dtReturn = new DataTable();
            // 保存列集合的属性信息数组
            PropertyInfo[] oProps = null;
            if (varlist == null) return dtReturn;//安全性检查
                                                 //循环遍历集合，使用反射获取类型的属性信息
            foreach (T rec in varlist)
            {
                //使用反射获取T类型的属性信息，返回一个PropertyInfo类型的集合
                if (oProps == null)
                {
                    oProps = ((Type)rec.GetType()).GetProperties();
                    //循环PropertyInfo数组
                    foreach (var pi in oProps)
                    {
                        var colType = pi.PropertyType;//得到属性的类型
                                                      //如果属性为泛型类型
                        if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()
                        == typeof(Nullable<>)))
                        {   //获取泛型类型的参数
                            colType = colType.GetGenericArguments()[0];
                        }
                        //将类型的属性名称与属性类型作为DataTable的列数据
                        dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
                    }
                }
                //新建一个用于添加到DataTable中的DataRow对象
                var dr = dtReturn.NewRow();
                //循环遍历属性集合
                foreach (PropertyInfo pi in oProps)
                {   //为DataRow中的指定列赋值
                    dr[pi.Name] = pi.GetValue(rec, null) == null ?
                        DBNull.Value : pi.GetValue(rec, null);
                }
                //将具有结果值的DataRow添加到DataTable集合中
                dtReturn.Rows.Add(dr);
            }
            return dtReturn;//返回DataTable对象
        }

        /// <summary>
        /// 集合 目前只能打印预览选中的一条数据
        /// </summary>
        public class PrintDataSourceList {
            /// <summary>
            /// 打印数据源实体类
            /// </summary>
            public PrintDataSource[] list { get; set; }
        }

        /// <summary>
        /// 打印数据源实体类 //{list:[{"Address":"收货地址","BillNo":"单号","ColorName":"颜色名称","Certification":"合格证","CompanyID":"品牌","ForeignName":" 洗涤标准",
        /// "FactCode":"制单号","LinkMan":"联系人","MaterialShortName":"货品简称","MatVendor":"物料供应商","Material":"物料","MaterialCode":"货号","MobilePhone":"电话",
        /// "RetailPrice":"吊牌价","Remark1":"充绒量","SendCheckNo":"执行标准","ShoetreeNo":"型号","StuffName":"物料成份","StyleCode":"款号","SUBSeries":"安全技术类别",
        /// "SexName":"性别","SizeNameNum":"多尺码","SizeName":"尺码","VendCustName":"供应商名称","BarCode":"条码","BillDate":"开单日期","CNStateName":"单据状态","ColorCode":"色号","KindName":"类别",
        /// "Qty":"销售数量","SeasonName":"季节","VendCustCode":"供应商编号","YearNo":"年份","SpareField1":"SpareField1","SpareField2":"SpareField2","SpareField3":"SpareField3"}]}
        /// </summary>
        public class PrintDataSource
        {
            /// <summary>
            /// 收货地址
            /// </summary>
            public string Address { get; set; }
            /// <summary>
            /// 单号
            /// </summary>
            public string BillNo { get; set; }
            /// <summary>
            /// 颜色名称
            /// </summary>
            public string ColorName { get; set; }
            /// <summary>
            /// 合格证
            /// </summary>
            public string Certification { get; set; }
            /// <summary>
            /// 品牌
            /// </summary>
            public string CompanyID { get; set; }
            /// <summary>
            /// 洗涤标准
            /// </summary>
            public string ForeignName { get; set; }
            /// <summary>
            /// 制单号
            /// </summary>
            public string FactCode { get; set; }
            /// <summary>
            /// 联系人
            /// </summary>
            public string LinkMan { get; set; }
            /// <summary>
            /// 货品简称
            /// </summary>
            public string MaterialShortName { get; set; }
            /// <summary>
            /// 物料供应商
            /// </summary>
            public string MatVendor { get; set; }
            /// <summary>
            /// 物料
            /// </summary>
            public string Material { get; set; }
            /// <summary>
            /// 货号
            /// </summary>
            public string MaterialCode { get; set; }
            /// <summary>
            /// 电话
            /// </summary>
            public string MobilePhone { get; set; }
            /// <summary>
            /// 吊牌价
            /// </summary>
            public string RetailPrice { get; set; }
            /// <summary>
            /// 充绒量
            /// </summary>
            public string Remark1 { get; set; }
            /// <summary>
            /// 执行标准
            /// </summary>
            public string SendCheckNo { get; set; }
            /// <summary>
            /// 型号
            /// </summary>
            public string ShoetreeNo { get; set; }
            /// <summary>
            /// 物料成份
            /// </summary>
            public string StuffName { get; set; }

            /// <summary>
            /// 款号
            /// </summary>
            public string StyleCode { get; set; }
            /// <summary>
            /// 安全技术类别
            /// </summary>
            public string SUBSeries { get; set; }
            /// <summary>
            /// 性别
            /// </summary>
            public string SexName { get; set; }
            /// <summary>
            /// 同款号下的所有尺码
            /// </summary>
            public string SizeNameNum { get; set; }
            /// <summary>
            /// 单个尺码
            /// </summary>
            public string SizeName { get; set; }
            /// <summary>
            /// 供应商名称
            /// </summary>
            public string VendCustName { get; set; }
            /// <summary>
            /// 条码
            /// </summary>
            public string BarCode { get; set; }
            /// <summary>
            /// 开单日期
            /// </summary>
            public string BillDate { get; set; }
            /// <summary>
            /// 单据状态
            /// </summary>
            public string CNStateName { get; set; }
            /// <summary>
            /// 色号
            /// </summary>
            public string ColorCode { get; set; }
            /// <summary>
            /// 类别
            /// </summary>
            public string KindName { get; set; }
            /// <summary>
            /// 销售数量
            /// </summary>
            public string Qty { get; set; }
            /// <summary>
            /// 季节
            /// </summary>
            public string SeasonName { get; set; }
            /// <summary>
            /// 供应商编号
            /// </summary>
            public string VendCustCode { get; set; }
            /// <summary>
            /// 年份
            /// </summary>
            public string YearNo { get; set; }
            /// <summary>
            /// 备用字段1
            /// </summary>
            public string SpareField1 { get; set; }
            /// <summary>
            /// 备用字段2
            /// </summary>
            public string SpareField2 { get; set; }
            /// <summary>
            /// 备用字段3
            /// </summary>
            public string SpareField3 { get; set; }
        }

    }
}
